package com.jwww.support.helper;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jwww.support.mybatis.IGenericEntityDao;
import com.jwww.support.mybatis.MybatisMapperResultConverter;
import com.jwww.support.mybatis.beans.PageObject;
import com.jwww.support.mybatis.beans.PageRequest;
import com.jwww.support.mybatis.query.EntityQuery;
import com.jwww.support.spring.InstanceFactory;

/**
 * 分页辅助类
 * 
 * @author jwww
 * @date 2015年4月20日下午5:32:03
 * @description <br>
 *              Copyright (c) 2015, vakinge@gmail.com.
 */
public class PageHelper {
	/**
	 * 
	 */
	private static final String REGEX_BLANK = "\\s+";

	private static final Logger LOGGER = LoggerFactory.getLogger(PageHelper.class);

	private static final String REGEX_NUMBER_10_13_BYTE = "\\d{10,13}";
	private static final String REGEX_CONT_DATE_TIME = ".*(date|time).*";

	/**
	 * 生成分页查询参数对象
	 * @param pageRequest
	 * @param queryRequest
	 * @return
	 */
	public static EntityQuery generateQueryParamsMap(PageRequest pageRequest,Object queryRequest,Class<?> entityClass) {
		
		EntityQuery para = new EntityQuery().entityClassName(entityClass);
		
		int start = (pageRequest.getPageNo() - 1)*pageRequest.getPageSize();
		para.startIndex(start).pageLimit(pageRequest.getPageSize());

		// 排序条件
		if (StringUtils.isNotBlank(pageRequest.getSortFields())) {
			para.sortAs(pageRequest.getSortFields());
			convertSortFields(para);
		}
		if (queryRequest == null)
			return para;
		
		Map<?, ?> map = queryRequest instanceof Map ? (Map<?, ?>)queryRequest : BeanConverter.beanToMap(queryRequest);

		String propName;
		Object value = null;
		Field[] declaredFields = entityClass.getDeclaredFields();

		for (Object key : map.keySet()) {
			propName = key.toString();
			value = map.get(key);

			if(value instanceof Enum<?>) {
				try {
					final Field field = getField(propName, declaredFields);

					if(field != null) {
						final Class<?> type = field.getType();

						if(type == String.class) {
							value = ((Enum<?>)value).name();
						} else if(type == Byte.class || type == byte.class){
							value = (byte)((Enum<?>) value).ordinal();
						} else if(type == Short.class || type == short.class){
							value = Short.valueOf(((Enum<?>) value).ordinal() + "");
						} else if(type == Long.class || type == long.class){
							value = Long.valueOf(((Enum<?>) value).ordinal() + "");
						} else {
							value = ((Enum<?>) value).ordinal();
						}
					}
				} catch (Exception e) {
					LOGGER.error(e.getMessage(), e);
				}
			} else if (propName.toLowerCase().matches(REGEX_CONT_DATE_TIME)) {
				if (value.toString().matches(REGEX_NUMBER_10_13_BYTE)) {
					value = new Date(Long.parseLong(value.toString()));
				} else{
					try {value = DateUtils.parseDate(value.toString(), new String[]{"yyyy-MM-dd HH:mm:ss"});} catch (Exception e) {}
				}
			}

			para.addParam(propName, value);
		}

		return para;
	}

	private static Field getField(String propName, Field[] declaredFields) {
		Field field = null;

		for (Field declaredField : declaredFields) {
            if(declaredField.getName().equals(propName)) {
                field = declaredField;

                break;
            }
        }
		return field;
	}

	/**
	 * 通用分页查询(需要外部构建查询条件map)
	 * 
	 * @param mapperClass
	 * @param resultClass
	 * @param params
	 *            查询条件
	 * @return
	 */
	public static <T> PageObject<T> pageQuery(Class<? extends IGenericEntityDao<?, ?>> mapperClass,Class<T> resultClass,EntityQuery params) {

		List<T> results = new ArrayList<T>();

		IGenericEntityDao<?, ?> dao = InstanceFactory.getInstance(mapperClass);

		Integer totalCount = dao.getCount(params);

		List<?> datas = dao.findListByPage(params);

		for (Object entity : datas) {
			results.add(BeanConverter.copy(entity, resultClass));
		}
		int pageNo = params.getStartIndex() / params.getPageLimit() + 1;
		return new PageObject<T>(pageNo, params.getPageLimit() ,results, totalCount);

	}

	/**
	 * 转换排序字段（实体字段->数据库字段）
	 * 
	 * @param params
	 */
	private static void convertSortFields(EntityQuery params) {
		if (params.getSortAs()==null||params.getSortAs().trim().equals(""))
			return;
		String sortAs = params.getSortAs();
		// field1 asc, field2 desc
		Map<String, String> sortMap = new TreeMap<String, String>();
		String[] sorts = sortAs.split(",");
		for (String sort : sorts) {
			String[] tmparr = sort.trim().split(REGEX_BLANK);
			sortMap.put(tmparr[0], tmparr.length == 2 ? tmparr[1].toUpperCase() : "ASC");
		}
		
		StringBuilder sortbuff = new StringBuilder();
		String columnName;
		for (String field : sortMap.keySet()) {
			columnName = MybatisMapperResultConverter.property2ColumnName(params.getEntityClass(), field);
			if(columnName != null){
				sortbuff.append(columnName).append(" ").append(sortMap.get(field)).append(",");
			}
		}
		if(sortbuff.length() > 0){
			sortbuff.deleteCharAt(sortbuff.length() - 1);
			params.sortAs(sortbuff.toString());
		}
	}

	public static void main(String[] args) {
		
	}
}
